package com.idea.dsl.client;

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.idea.dsl.config.DslProperties;
import com.idea.dsl.model.ModelRequest;
import com.idea.dsl.model.ModelResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 千问模型客户端实现 - 使用官方DashScope SDK
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class QianWenClient implements ModelClient {

    private final DslProperties dslProperties;

    private static final String CLIENT_TYPE = "qianwen";
    
    @Override
    public ModelResponse chat(ModelRequest request) {
        try {
            DslProperties.ModelConfig config = dslProperties.getModels().get(CLIENT_TYPE);
            if (config == null) {
                throw new RuntimeException("千问配置未找到");
            }

            log.debug("开始调用千问模型: {}", config.getModel());

            // 构建消息列表
            List<Message> messages = buildMessages(request);

            // 构建生成参数
            GenerationParam param = GenerationParam.builder()
                    .model(config.getModel())
                    .messages(messages)
                    .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                    .topP(0.8)
                    .apiKey(config.getApiKey())
                    .build();

            // 设置可选参数
            if (request.getMaxTokens() != null) {
                param.setMaxTokens(request.getMaxTokens());
            } else if (config.getMaxTokens() != null) {
                param.setMaxTokens(config.getMaxTokens());
            }

            if (request.getTemperature() != null) {
                param.setTemperature(request.getTemperature().floatValue());
            }

            // 调用千问API
            Generation gen = new Generation();
            GenerationResult result = gen.call(param);

            log.debug("千问响应状态: {}", result.getRequestId());

            return convertFromDashScopeResult(result);

        } catch (ApiException | NoApiKeyException | InputRequiredException e) {
            log.error("千问API调用异常", e);
            throw new RuntimeException("千问API调用异常: " + e.getMessage(), e);
        } catch (Exception e) {
            log.error("千问请求异常", e);
            throw new RuntimeException("千问请求异常: " + e.getMessage(), e);
        }
    }
    
    /**
     * 构建DashScope消息列表
     */
    private List<Message> buildMessages(ModelRequest request) {
        List<Message> messages = new ArrayList<>();

        if (request.getMessages() != null) {
            for (ModelRequest.Message msg : request.getMessages()) {
                Role role;
                switch (msg.getRole().toLowerCase()) {
                    case "system":
                        role = Role.SYSTEM;
                        break;
                    case "assistant":
                        role = Role.ASSISTANT;
                        break;
                    case "user":
                    default:
                        role = Role.USER;
                        break;
                }

                Message message = Message.builder()
                        .role(role.getValue())
                        .content(msg.getContent())
                        .build();
                messages.add(message);
            }
        }

        // 如果没有消息，添加一个默认的用户消息
        if (messages.isEmpty()) {
            messages.add(Message.builder()
                    .role(Role.USER.getValue())
                    .content("请生成DSL")
                    .build());
        }

        return messages;
    }
    
    /**
     * 转换DashScope响应为标准格式
     */
    private ModelResponse convertFromDashScopeResult(GenerationResult result) {
        String content = "";
        String finishReason = "stop";

        // 提取响应内容
        if (result.getOutput() != null && result.getOutput().getChoices() != null &&
            !result.getOutput().getChoices().isEmpty()) {

            com.alibaba.dashscope.aigc.generation.GenerationOutput.Choice choice =
                result.getOutput().getChoices().get(0);

            if (choice.getMessage() != null) {
                content = choice.getMessage().getContent();
            }

            if (choice.getFinishReason() != null) {
                finishReason = choice.getFinishReason();
            }
        }

        // 构建消息
        ModelRequest.Message message = ModelRequest.Message.builder()
                .role("assistant")
                .content(content)
                .build();

        ModelResponse.Choice responseChoice = ModelResponse.Choice.builder()
                .index(0)
                .message(message)
                .finishReason(finishReason)
                .build();

        // 构建使用情况
        ModelResponse.Usage usage = null;
        if (result.getUsage() != null) {
            usage = ModelResponse.Usage.builder()
                    .promptTokens(result.getUsage().getInputTokens())
                    .completionTokens(result.getUsage().getOutputTokens())
                    .totalTokens(result.getUsage().getTotalTokens())
                    .build();
        }

        return ModelResponse.builder()
                .id(result.getRequestId())
                .model(result.getOutput() != null ? result.getOutput().getChoices().get(0).getMessage().getRole() : "qwen")
                .choices(Arrays.asList(responseChoice))
                .usage(usage)
                .created(System.currentTimeMillis() / 1000)
                .build();
    }
    
    @Override
    public String getClientType() {
        return CLIENT_TYPE;
    }
    
    @Override
    public boolean isAvailable() {
        DslProperties.ModelConfig config = dslProperties.getModels().get(CLIENT_TYPE);
        return config != null && StringUtils.isNotBlank(config.getApiKey());
    }
}
